#include <buola/scene.h>
#include <buola/scene/csceneview.h>
#include <buola/scene/ccamera.h>
#include <buola/scene/cperspectivecamera.h>
#include <buola/scene/cscene.h>
#include <buola/scene/geodes/ccube.h>
#include <buola/scene/geodes/csphere.h>
#include <buola/scene/geodes/cplane.h>
#include <buola/scene/geodes/ccylinder.h>
#include <buola/scene/geodes/ccapsule.h>
#include <buola/scene/transform/crttransform.h>
#include <buola/scene/transform/crigidbody.h>
#include <buola/scene/transform/csoftbody.h>
#include <buola/scene/cimagerenderer.h>
#include <buola/scene/controllers/ccameracontroller.h>
#include <buola/scene/controllers/cphysicscontroller.h>
#include <buola/image/io.h>
#include <buola/image/cgc.h>
#include <buola/gui/ctoolkit.h>
#include <buola/app/capp.h>

using namespace buola;

int main(int pNArg,char **pArgs)
{
    buola_init(pNArg,pArgs);

    try
    {
        CApp lApp;

        gui::get_toolkit()->GetOpenGLGC()->MakeCurrent(); ///\todo remove this ugly hack!
        
        //create the scene
        scene::PScene lScene=new scene::CScene(true);
        scene::PRigidBody lSphere1=new scene::CRigidBody(new scene::CSphere,0,mat::translation_3d({0,0,3}));
        lScene->World()->AddChild(lSphere1);
        scene::PRigidBody lPlane=new scene::CRigidBody(new scene::CCube(50,50,50),0,mat::translation_3d({0,0,-25}));
        lScene->World()->AddChild(lPlane);
        
        std::array<mat::CVec3f,4> lCorners{{{-3,-3,5},{3,-3,5},{-3,3,5},{3,3,5}}};
        scene::PSoftBody lCloth=new scene::CSoftBody(new scene::CCloth(lCorners,1,50,50));
        lScene->World()->AddChild(lCloth);

        lScene->AddBody(lPlane);
        lScene->AddBody(lSphere1);
        lScene->AddBody(lCloth);
        
        scene::PPerspectiveCamera lCamera=new scene::CPerspectiveCamera;
        lCamera->LookAt({0,0,2},{25,0,2},{0,0,1});

        scene::CImageRenderer lRenderer;
        lRenderer.SetCamera(lCamera);
        lRenderer.AddScene(lScene);

        img::CImage_rgb8 lImage({640,640});
        
        lRenderer.GetImage(lImage);

        img::save(lImage,io::file("scene.ppm"));
        
        scene::PSceneView lView=new scene::CSceneView;
        lView->SetCamera(lCamera);
        lView->AddScene(lScene);
        lView->AddController(new scene::CCameraController(lCamera));
        lView->AddController(new scene::CPhysicsController(lScene));
        lView->Map(CSize_d(800,600));
        
        lApp.Run();
    }
    catch(std::exception &pE)
    {
        msg_info() << pE.what() << "\n";
    }

    return buola_finish();
}